

-- Namespace
	local _,mod = ...


-- Object ref
	local RAID_CLASS_COLORS = CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS


-- Constants
	local font = {mod.path..'media\\bavaria.ttf',8,'OUTLINEMONOCHROME'}
	
	local c_bar =    {.16,.16,.16}
	local c_barbg =  {.33,.33,.33}
	local c_border = {.07,.07,.07}
	
	local c_hlite = {.52,.20,.20}
	
	local white = { r = 1, g = 1, b = 1 }


-- Helpers
	local function dim(color,perc)
		local r,g,b = color.r,color.g,color.b
		r,g,b = r*perc,g*perc,b*perc
		return r,g,b
	end


-- Base frame
	local player = mod:UF('player')
		player:SetFrameLevel(2)
		player:SetHeight(130) player:SetWidth(17)
		player:SetPoint('BOTTOMLEFT',UIParent,'CENTER',-232,-164)
		
		player:SetScript('OnEnter',function(self)
			GameTooltip_SetDefaultAnchor(GameTooltip,self)
			GameTooltip:SetUnit(self.unit)
		end)
		player:SetScript('OnLeave',function(self)
			GameTooltip:ClearLines()
			GameTooltip:Hide()
		end)
	
	local bg = player:CreateTexture(nil,'BACKGROUND')
		bg:SetAllPoints(true)
		bg:SetTexture(unpack(c_border))
		player.bg = bg


-- Health
	local hpbar = player:CreateTexture(nil,'ARTWORK')
		hpbar:SetHeight(128) hpbar:SetWidth(11)
		hpbar:SetPoint('BOTTOMLEFT',1,1)
		hpbar:SetTexture(unpack(c_bar))
		hpbar:Listen('health',function(self,min,max)
			local perc = min / max
			if perc <= 0 then
				perc = .001
			elseif perc > 1 then
				perc = 1
			end
			self:SetHeight(128*perc)
		end)
		player.hpbar = hpbar
	
	local inchealbar = player:CreateTexture(nil,'ARTWORK')
		inchealbar:SetHeight(128) inchealbar:SetWidth(11)
		inchealbar:SetPoint('BOTTOM',hpbar,'TOP')
		inchealbar:SetTexture(.2,.6,.2)
		inchealbar:Hide()
		inchealbar:Listen('incheal',function(self,heal,min,max)
			if heal then
				self:Show()
				local def = 1 - (min / max)
				local perc = heal / max
				if perc > def then
					perc = def
				end
				if perc <= 0 then
					perc = .001
				elseif perc > 1 then
					perc = 1
				end
				self:SetHeight(128*perc)
			else
				self:Hide()
			end
		end)
		player.inchealbar = inchealbar
	
	local hpbg = player:CreateTexture(nil,'BORDER')
		hpbg:SetHeight(128) hpbg:SetWidth(11)
		hpbg:SetPoint('BOTTOMLEFT',1,1)
		hpbg:SetTexture(unpack(c_barbg))
		player.hpbg = hpbg


-- Power
	local ppbar = player:CreateTexture(nil,'ARTWORK')
		ppbar:SetHeight(128) ppbar:SetWidth(3)
		ppbar:SetPoint('BOTTOMRIGHT',-1,1)
		ppbar:SetTexture(unpack(c_hlite))
		ppbar:Listen('power',function(self,min,max)
			local perc = min / max
			if perc <= 0 then
				perc = .001
			elseif perc > 1 then
				perc = 1
			end
			self:SetHeight(128*perc)
		end)
		ppbar:Listen('class',function(self,_,enclass)
			local color = RAID_CLASS_COLORS[enclass] or white
			self.classcolor = color
			self:SetTexture(dim(color,.75))
		end)
		ppbar:Listen('combat',function(self,incombat)
			if incombat then
				self:SetTexture(.6,.2,.2)
			else
				local color = self.classcolor or white
				self:SetTexture(dim(color,.75))
			end
		end)
		player.ppbar = ppbar
	
	local ppbg = player:CreateTexture(nil,'BORDER')
		ppbg:SetHeight(128) ppbg:SetWidth(3)
		ppbg:SetPoint('BOTTOMRIGHT',-1,1)
		ppbg:SetTexture(unpack(c_barbg))
		player.ppbg = ppbg
	
	local pptext = player:CreateFontString(nil,'ARTWORK')
		pptext:SetPoint('BOTTOMRIGHT',player,'BOTTOMLEFT',-1,4.5)
		pptext:SetFont(unpack(font))
		pptext:SetJustifyH('RIGHT')
		pptext:Listen('power',function(self,min)
			local text
			if min > 999999 then
				text = ('%.1fM'):format(min/1000000)
			elseif min > 9999 then
				text = ('%.1fk'):format(min/1000)
			else
				text = ('%d'):format(min)
			end
			self:SetText(text)
		end)
		pptext:Listen('class',function(self,_,enclass)
			local color = RAID_CLASS_COLORS[enclass] or white
			self:SetTextColor(color.r,color.g,color.b)
		end)
		local function pp_hide()
			pptext:Hide()
		end
		pptext:Listen('combat',function(self,incombat)
			if incombat then
				if self.hidden then
					self:Show()
					self.hidden = false
					mod:timer_unregister(pp_hide)
				end
			elseif not self.hidden then
				mod:timer_register(4,false,pp_hide)
				self.hidden = true
			end
		end)
		pptext:Hide()
		pptext.hidden = true
		player.pptext = pptext


-- GCD
	local gcdtick = player:CreateTexture(nil,'OVERLAY')
		gcdtick:SetZLevel(1)
		gcdtick:SetHeight(2) gcdtick:SetWidth(3)
		gcdtick:Hide()
		gcdtick:SetTexture(.8,.8,.8)
		gcdtick.anim = function(elapsed)
			local self = gcdtick
			local min,max = self.min,self.max
			min = min + elapsed
			if min >= max then
				self:Hide()
				self.min = nil
				self.max = nil
				mod:anim_unregister(self.anim)
			else
				self:ClearAllPoints()
				self:SetPoint('BOTTOMRIGHT',-1,1+126*(min/max))
				self.min = min
			end
		end
		gcdtick:Listen('gcd',function(self,start,dur)
			if start then
				self:Show()
				self.min = GetTime()-start
				self.max = dur
				mod:anim_register(self.anim)(0)
			else
				self:Hide()
				self.min = nil
				self.max = nil
				mod:anim_unregister(self.anim)
			end
		end)
		player.gcdtick = gcdtick


-- Threat
	local threattick = player:CreateTexture(nil,'OVERLAY')
		threattick:SetZLevel(1)
		threattick:SetHeight(2) threattick:SetWidth(11)
		threattick:Hide()
		threattick:SetTexture(.4,.8,.4)
		threattick:Listen('threat',function(self,valid,tank,_,tpct)
			if valid then
				self:Show()
				local tpct = tpct * .01
				if tpct <= 0 then
					tpct = .001
				elseif tpct > 1 then
					tpct = 1
				end
				if tank then
					self:SetTexture(.8,.8,.4)
				else
					self:SetTexture(.4,.8,.4)
				end
				self:ClearAllPoints()
				self:SetPoint('BOTTOMLEFT',1,1+126*tpct)
			else
				self:Hide()
			end
		end)
		player.threattick = threattick


-- Experience
	local exptick = player:CreateTexture(nil,'ARTWORK')
		exptick:SetZLevel(1)
		exptick:SetHeight(2) exptick:SetWidth(11)
		exptick:Hide()
		exptick:SetTexture(.8,.4,.8)
		exptick:Listen('experience',function(self,min,max,exh)
			if min then
				self:Show()
				local perc = min / max
				if perc <= 0 then
					perc = .001
				elseif perc > 1 then
					perc = 1
				end
				self:ClearAllPoints()
				self:SetPoint('BOTTOMLEFT',1,1+126*perc)
				if exh and exh > 0 then
					self:SetTexture(.2,.4,.8)
				else
					self:SetTexture(.8,.4,.8)
				end
			else
				self:Hide()
			end
		end)
		player.exptick = exptick


-- Casting
	local castbar = player:CreateTexture(nil,'OVERLAY')
		castbar:SetHeight(128) castbar:SetWidth(3)
		castbar:SetPoint('BOTTOMLEFT',player,'BOTTOMRIGHT',5,1)
		castbar:Hide()
		castbar:SetTexture(unpack(c_hlite))
		castbar.anim = function(elapsed)
			local self = castbar
			local min,max = self.min,self.max
			min = min + elapsed; self.min = min
			local perc = min / max
			if self.channel then
				perc = 1 - perc
			end
			if perc <= 0 then
				perc = .001
			elseif perc > 1 then
				perc = 1
			end
			self:SetHeight(perc*128)
		end
		castbar:Listen('casting',function(self,name,_,startT,endT,_,channel)
			if name then
				self:Show()
				self.min = GetTime() - startT
				self.max = endT - startT
				self.channel = channel
				mod:anim_register(self.anim)(0)
			else
				self:Hide()
				self.min = nil
				self.max = nil
				self.channel = nil
				mod:anim_unregister(self.anim)
			end
		end)
		castbar:Listen('class',function(self,_,enclass)
			local color = RAID_CLASS_COLORS[enclass] or white
			self:SetTexture(dim(color,.75))
		end)
		player.castbar = castbar
	
	local castbarbg = player:CreateTexture(nil,'BORDER')
		castbarbg:SetHeight(128) castbarbg:SetWidth(3)
		castbarbg:SetPoint('BOTTOMLEFT',player,'BOTTOMRIGHT',5,1)
		castbarbg:Hide()
		castbarbg:SetTexture(unpack(c_barbg))
		castbarbg:Listen('casting',function(self,name)
			if name then
				self:Show()
			else
				self:Hide()
			end
		end)
		player.castbarbg = castbarbg
	
	local castbarborder = player:CreateTexture(nil,'BACKGROUND')
		castbarborder:SetHeight(130) castbarborder:SetWidth(5)
		castbarborder:SetPoint('BOTTOMLEFT',player,'BOTTOMRIGHT',4,0)
		castbarborder:Hide()
		castbarborder:SetTexture(unpack(c_border))
		castbarborder:Listen('casting',function(self,name)
			if name then
				self:Show()
			else
				self:Hide()
			end
		end)
		player.castbarborder = castbarborder
	
	local castlatency = player:CreateTexture(nil,'ARTWORK')
		castlatency:SetHeight(128) castlatency:SetWidth(3)
		castlatency:Hide()
		castlatency:SetTexture(.2,.6,.2)
		castlatency.timer = function(elapsed)
			local self = castlatency
			local _,_,_,lat = GetNetStats()
			local perc = (lat * .001) / self.max
			if perc <= 0 then
				perc = .001
			elseif perc > 1 then
				perc = 1
			end
			self:SetHeight(128*perc)
		end
		castlatency:Listen('casting',function(self,name,_,startT,endT,_,channel)
			if name then
				self:ClearAllPoints()
				if channel then
					self:SetPoint('BOTTOM',castbarbg,'BOTTOM',0,0)
				else
					self:SetPoint('TOP',castbarbg,'TOP',0,0)
				end
				self:Show()
				self.max = endT - startT
				mod:timer_register(.2,true,self.timer)(0)
			else
				self:Hide()
				self.max = nil
				mod:timer_unregister(self.timer)
			end
		end)
		player.castlatency = castlatency
	
	local castname = player:CreateFontString(nil,'OVERLAY')
		castname:SetPoint('TOPRIGHT',castbarborder,'BOTTOMRIGHT',4,-4)
		castname:SetFont(unpack(font))
		castname:SetJustifyH('RIGHT')
		castname:Listen('casting',function(self,name)
			if not name then name = '' end
			self:SetText(name)
		end)
		player.castname = castname
	
	local casttime = player:CreateFontString(nil,'OVERLAY')
		casttime:SetPoint('TOPLEFT',castbarborder,'TOPRIGHT',4,0)
		casttime:SetFont(unpack(font))
		casttime:SetJustifyH('LEFT')
		casttime:Hide()
		casttime.timer = function(elapsed)
			local self = casttime
			local min,max = self.min,self.max
			min = min + elapsed; self.min = min
			self:SetText(('%.1f'):format(max-min))
		end
		casttime:Listen('casting',function(self,name,_,startT,endT)
			if name then
				self:Show()
				self.min = GetTime() - startT
				self.max = endT - startT
				mod:timer_register(0,true,self.timer)(0)
			else
				self:Hide()
				self.min = nil
				self.max = nil
				mod:timer_unregister(self.timer)
			end
		end)
		player.casttime = casttime
